<template>
	<view class="lrl-grid-album" :id="domId">
		<view v-for="(item, index) in showList"
			class="lrl-grid-album-wrapper"
			:key="index"
			:style="[imgWrapperStyles(index)]"
			@click="itemClick(item, index)"
		>
			<image :src="item" class="lrl-grid-album-img" :mode="props.mode"></image>
			<view class="lrl-grid-album-maxcount" v-if="props.urls.length > showList.length && index === showList.length - 1">
				<text class="lrl-grid-album-maxcount-txt" :style="[{ fontSize: baseSize * 0.2 + 'px' }]">+{{ props.urls.length - showList.length }}</text>
			</view>
		</view>
	</view>
</template>

<script setup>
import { computed, onMounted, ref, getCurrentInstance, nextTick } from 'vue';
import { addUnit, addStyle } from '@/uni_modules/uview-plus/libs/function/index';
import { getRandomLetter } from '../../libs/util/tools.js';
/**
 * lrl-grid-album 类似微信朋友圈的自动计算宽度的宫格相册
 * @description lrl-grid-album 类似微信朋友圈的自动计算宽度的宫格相册
 * @author ruilin
 * @property {Array}                          urls                图片列表
 * @property {String|Number}                  radius              圆角
 * @property {String}                         mode                图片裁切模式
 * @property {String|Number}                  rowNum              图片一行展示多少个，不传将会自动按照微信朋友圈的方式排列
 * @property {String|Number}                  rowGapSize          图片水平间隔距离
 * @property {String|Number}                  columnGapSize       图片垂直间隔距离
 * @property {String|Number}                  heightScale         图片高度与宽度的比例
 * @property {String|Number}                  maxCount            最大展示图片数量，超出的会在最后一张图片显示超出数量
 * @property {Boolean}                        previewImage        是否可预览图片
 * @event {Function()}                        click               点击图片
 * @example <lrl-grid-album></lrl-grid-album>
 */
const props = defineProps({
	// 图片列表
	urls: {
		type: [Array],
		default: () => []
	},
	mode: {
		type: [String],
		default: 'aspectFill',
		validator(value){
			// 不能使用宽度自动的模式，会导致尺寸错误
			return !['heightFix'].includes(value)
		}
	},
	radius: {
		type: [String, Number],
		default: '20rpx'
	},
	rowNum: {
		type: [String, Number],
		default: null
	},
	rowGapSize: {
		type: [String, Number],
		default: '20rpx'
	},
	heightScale: {
		type: [String, Number],
		default: 1
	},
	columnGapSize: {
		type: [String, Number],
		default: '20rpx'
	},
	previewImage: {
		type: Boolean,
		default: false
	},
	maxCount: {
		type: [String, Number],
		default: 6
	}
});
const instance = getCurrentInstance()

const domId = ref(getRandomLetter(10))

const emit = defineEmits(['click'])

const gridAlbumRef = ref(null)
// 图片包装盒子宽度
const imgBoxWidth = ref(uni.upx2px(600));
// 循环显示的数组
const showList = computed(() => props.urls.slice(0, parseInt(props.maxCount) ))
// 图片上下左右间隔
const rowGapWidthForPx = computed(() => {
	if(props.rowGapSize.indexOf('rpx') >= 0){
		return uni.upx2px(props.rowGapSize.replace(/rpx/, ''))
	}else if(props.rowGapSize.indexOf('px') >= 0){
		return parseInt(props.rowGapSize.replace(/px/, ''))
	}else {
		return parseInt(props.rowGapSize)
	}
})
// 计算一行多少个图片
const rowNum = computed(() => {
	const length = props.urls.length;
	return props.rowNum ? props.rowNum : (length <= 2 || length === 4 ? 2 : 3)
})
// 计算单张图片宽度
const baseSize = computed(() => {
	return (imgBoxWidth.value - rowGapWidthForPx.value * (rowNum.value - 1)) / rowNum.value
})
// 单张图片样式
const imgWrapperStyles = computed(() => {
	return (index) => ({
		borderRadius: addUnit(props.radius),
		width: baseSize.value + 'px',
		height: baseSize.value * parseFloat(props.heightScale) + 'px',
		marginRight: (index + 1) % rowNum.value !== 0 ?  rowGapWidthForPx.value + 'px' : '0',
		marginBottom: addUnit(props.columnGapSize)
	});
})

onMounted(() => {
	initSize()
})
/**
 * 初始化获取图片盒子宽度
 */
const initSize = () => {
	nextTick(() => {
		const query = uni.createSelectorQuery().in(instance.proxy);
		query.select('#' + domId.value)
			.boundingClientRect((res) => {
				if (res) {
					imgBoxWidth.value = res.width;
				}
			})
			.exec();
	})
}
/**
 * 点击图片
 * @param {String} url
 * @param {Number} index
 */
const itemClick = (url, index) => {
	emit('click', { url, index })
	if(props.previewImage){
		uni.previewImage({
			urls: props.urls,
			current: index,
			indicator: 'number'
		})
	}
}

defineExpose({
	// 如有宽度变化,调用此方法刷新宽度
	initSize
})
</script>

<style scoped lang="scss">
.lrl-grid-album{
	display: flex;
	flex-direction: row;
	flex-wrap: wrap;
	
	.lrl-grid-album-wrapper{
		position: relative;
		overflow: hidden;
		
		.lrl-grid-album-img{
			width: 100%;
			height: 100%;
		}
		
		.lrl-grid-album-maxcount{
			position: absolute;
			z-index: 3;
			top: 0;
			right: 0;
			left: 0;
			bottom: 0;
			display: flex;
			align-items: center;
			justify-content: center;
			background-color: rgba(0,0,0,0.3);
			
			.lrl-grid-album-maxcount-txt{
				color: #fff;
				font-weight: 300;
			}
		}
	}
}
</style>
